package csl.blog.common.annotation.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import csl.blog.common.exception.BlogException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

/**
 * @Description: TODO 有效文件校验实现切面类
 * @author: 隔山海
 * @date: 2021年08月13日 21:35
 */
@Component
@Aspect
public class CheckFileTypeAspect {

    /**
     * 切面参数列表类型
     */
    private static String[] types = {"java.lang.Integer", "java.lang.Double",
            "java.lang.Float", "java.lang.Long", "java.lang.Short",
            "java.lang.Byte", "java.lang.Boolean", "java.lang.Char",
            "java.lang.String", "int", "double", "long", "short", "byte",
            "boolean", "char", "float"};

    // 图片类型数组
    String[] img = {"bmp", "jpg", "jpeg", "png", "tiff", "gif", "pcx", "tga", "exif", "fpx", "svg", "psd",
            "cdr", "pcd", "dxf", "ufo", "eps", "ai", "raw", "wmf"};
    // 文档类型数组
    String[] document = {"txt", "doc", "docx", "xls", "xlsx", "htm", "html", "jsp", "rtf", "wpd", "pdf", "ppt",
            "pptx"};
    // 视频类型数组
    String[] video = {"mp4", "avi", "mov", "wmv", "asf", "navi", "3gp", "mkv", "f4v", "rmvb", "webm"};

    // 音乐类型数组
    String[] music = {"mp3", "wma", "wav", "mod", "ra", "cd", "md", "asf", "aac", "vqf", "ape", "mid", "ogg",
            "m4a", "vqf"};

    @Around("@annotation(csl.blog.common.annotation.CheckFileType)")
    public Object invoke(ProceedingJoinPoint point) throws Throwable{
        Signature signature = point.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        String fileName = null;
        int idx = 0;
        // 参数名称数组
        String[] parameterNames = methodSignature.getParameterNames();
        // 参数类型列表
        Class[] parameterTypes = methodSignature.getParameterTypes();
        // 先判断是否存在有fileName的名字的参数
        for (int i = 0; i < parameterNames.length; i++) {
            if("fileName".equals(parameterNames[i])) {
                Class parameterType = parameterTypes[idx];
                if(parameterType.equals(String.class)){
                    fileName = (String) point.getArgs()[idx];
                }
            }
        }

        // 没有命名为fileName的String参数，则取不是基本类型的对象转化为JSON取fileName值
        if(fileName == null) {
            for (int i = 0; i < parameterTypes.length; i++) {
                boolean isBaseType = false;
                for (String type : types) {
                    if(parameterTypes[i].getName().equals(type)) {
                        isBaseType = true;
                        break;
                    }
                }
                if(!isBaseType) {
                    JSONObject jsonObject = JSONUtil.parseObj(point.getArgs()[i]);
                    fileName = jsonObject.getStr("fileName");
                }
            }
        }
        if (fileName!=null && !isFileName(fileName)){
            throw new BlogException("异常文件，请选择正常文件！");
        }
        return point.proceed();
    }

    /**
     * 校验是不是正确的文件
     * @param fileName 文件名称
     * @return 返回校验结果
     */
    private boolean isFileName(String fileName){
//        获取文件后缀并转为小写
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
//        校验图片类型
        for (String s : img) {
            if (s.equals(suffix)) {
                return true;
            }
        }
//        校验文本类型
        for (String s : document) {
            if (s.equals(suffix)){
                return true;
            }
        }
//        校验视频文件
        for (String s : video) {
            if (s.equals(suffix)){
                return true;
            }
        }
//        校验音乐文件
        for (String s : music) {
            if (s.equals(suffix)){
                return true;
            }
        }
        return false;
    }
}
